//
//  SLIbeaconManager.m
//  SlockApp
//
//  Created by 凯朱 on 2024/9/24.
//

#import "SLIbeaconManager.h"

static  NSString *const kIBeaconUUID = @"BC65CACA-50A9-42AD-889C-DC5F84EA6213";

@interface SLIbeaconManager()<CLLocationManagerDelegate>{
    CLLocation *_userLocation;
    NSInteger _lastTime;
}
@property (nonatomic, strong)CLLocationManager *locationManager;
@property (nonatomic, strong)CLBeaconRegion *region;
@property (nonatomic, strong)NSMutableArray *dbDeviceList;/*当前双模开锁的设置列表*/

@end

@implementation SLIbeaconManager
+(instancetype)sharedManager{
    static SLIbeaconManager * instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

//开始监听区域 - 双模开锁
-(void)startUserDeviceMonitoring{
    
    NSArray *deviceList = [UserManager getUserDeviceList];
    if (deviceList.count == 0) {
        [self.locationManager stopRangingBeaconsInRegion:self.region];
        return;
    }
    if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [self.locationManager requestAlwaysAuthorization];
    }
    
    _dbDeviceList = [NSMutableArray new];
    [deviceList enumerateObjectsUsingBlock:^(SLLockModel *model, NSUInteger idx, BOOL * _Nonnull stop) {
        if (model.isGuest) {
            return;
        }
        if (model.isOpenDbModel) {
            [_dbDeviceList addObject:model];
        }
    }];
    
    //没有双模开锁的设备
    if (_dbDeviceList.count == 0) {
//        [self.locationManager stopRangingBeaconsInRegion:_region];
        return;
    }
  
    //开始定位用户的位置
    [self.locationManager startUpdatingLocation];
    //Monitoring用来监测是否进入到一个iBeacon的基站区域内，Ranging则用来获取这个区域内所有iBeacon的信息(startRangingBeaconsInRegion,startMonitoringForRegion)
    //当App进入到后台后，Monitoring可以继续运行，而Ranging则不行
    [self.locationManager startMonitoringForRegion:self.region];
}

-(void)startBackgoundMonitoring{
    [self.locationManager startMonitoringForRegion:self.region];
}

//进入iBeacon 区域的回调
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
    NSString *message = @"";
    BOOL isHaveMagicDevice = NO;
    if ([region isKindOfClass:[CLBeaconRegion class]]) {
        CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region;
        // 获取 iBeacon 的标识符
        NSString *uuidString = beaconRegion.proximityUUID.UUIDString;
        NSString *identifier = beaconRegion.identifier;
        // 如果需要，可以启动 iBeacon 的监测
        if ([uuidString isEqualToString:kIBeaconUUID]) {
            isHaveMagicDevice = YES;
            message = [NSString stringWithFormat:@"进入了智锁ibeacon电子围栏范围 uuidString = %@ Identifier = %@",uuidString,identifier];
        }
    }
    /*
     当你接收到基站信号的时候这个方法就开始执行（当然你要离基站足够近）。然后调用locationManager的startRagingBeaconsInRegion方法，传入我们之前定义好的beaconRegion属性。
     */
    if (isHaveMagicDevice) {
        NSLog(@"%@",message);
        [self.locationManager startRangingBeaconsInRegion:self.region];
    }
}

//进程kill之后，进入iBeacon 区域的回调
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{
    NSString *stateString = nil;
    switch (state) {
        case CLRegionStateInside:
            stateString = @"inside";
            break;
        case CLRegionStateOutside:
            stateString = @"outside";
            break;
        case CLRegionStateUnknown:
            stateString = @"unknown";
            break;
    }
    BOOL isHaveMagicDevice = NO;
    NSString *message = @"";
    if ([region isKindOfClass:[CLBeaconRegion class]]) {
        CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region;
        NSString *uuidString = beaconRegion.proximityUUID.UUIDString;
        NSString *uuid = [uuidString componentsSeparatedByString:@"-"].lastObject;
        // 如果需要，可以启动 iBeacon 的监测
        if ([uuidString isEqualToString:kIBeaconUUID]) {
            isHaveMagicDevice = YES;
            message = [NSString stringWithFormat:@"后台ibeacon状态变更%@ uuid = %@ major = %@ minor = %@",stateString,uuid,beaconRegion.major,beaconRegion.minor];
//            [ZCTool showLocalNotfyAlertWith:@"提示" body:message];
        }
    }
    if (isHaveMagicDevice) {
        [self.locationManager startRangingBeaconsInRegion:self.region];
    }
}

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{
    NSLog(@"Exited region: %@", region);
//    [ZCTool showLocalNotfyAlertWith:@"提示" body:@"离开了ibeacon电子围栏范围"];
    //停止搜索
    [self.locationManager stopRangingBeaconsInRegion:self.region];
}

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region{
    NSLog(@"开始后台监听ibaecon");
}

-(void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(nullable CLRegion *)region withError:(NSError *)error{
    NSLog(@"开始后台监听ibaecon失败 %@",error.description);
}

//当你从足够远（10～20米）的地方想基站的方向走的时候，didEnterRange 和 didRangeBeacons方法就会被调用，这时就可以从方法中传入的beacon数组中取出值来现实在界面上。
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region{
    __block NSString *msg;
//    NSLog(@"ibeacon count = %ld",(unsigned long)beacons.count);
    if (beacons.count <= 0) {
        msg = @"没有发现ibeacon";
//        kShowToast(msg);
//        NSLog(@"没有ibeacon");
        return;
    }
    
    //已经连接上了,或者正在连接中或搜索中，在指定页面不要去连接
    NSString *vcName = NSStringFromClass([[ZCTool getCurrentUIVC] class]);
    if (kCurDevice || kCurClickDevice 
        || [vcName isEqualToString:@"SLAddLockScanVC"]
        || [vcName isEqualToString:@"SLSetLockNameVC"]
        || [SLBluetoothManager sharedManager].isConnecting
        || [SLBluetoothManager sharedManager].isSearching
        ) {
        return;
    }
    
    __block SLLockModel *_tryConnectBeacon = nil;
    for (CLBeacon * beacon in beacons) {
        NSString *proximityUUID = [NSString stringWithFormat:@"%@",beacon.proximityUUID?beacon.proximityUUID.UUIDString:@""];
        NSString *major = [NSString stringWithFormat:@"%@",beacon.major?beacon.major.stringValue:@""];
        NSString *minor = [NSString stringWithFormat:@"%@",beacon.minor?beacon.minor.stringValue:@""];
        double distance = beacon.accuracy;
        
        NSString *majorStr;
        NSString *minorStr;
        NSString *hexStr1 = [DataCoverTool coverFromIntToHex:[major integerValue]];
        NSString *hexStr2 = [DataCoverTool coverFromIntToHex:[minor integerValue]];
        majorStr = [DataCoverTool coverFromHexStringToStr:hexStr1];
        minorStr = [DataCoverTool coverFromHexStringToStr:hexStr2];
        msg = [NSString stringWithFormat:@"发现ibeacon设备 proximityUUID = %@, major = %@,minor=%@ distance = %.1f米",proximityUUID,majorStr,minorStr,distance];
        NSInteger now = [[[NSDate date] timestamp] integerValue];
        
        if (now - _lastTime > 30) {
            _lastTime = now;
            [UserManager updateLogViewWithMessage:msg needUnicode:NO];
        }
//        NSLog(@"%@",msg);
        if (majorStr.length > 0 && minorStr.length > 0) {
            [_dbDeviceList enumerateObjectsUsingBlock:^(SLLockModel *model, NSUInteger idx, BOOL * _Nonnull stop) {
                //匹配到了设备 - 并且在范围内
                BOOL isRightDevice = [model.major isEqualToString:majorStr] && [model.minor isEqualToString:minorStr] && [proximityUUID isEqualToString:kIBeaconUUID];
                if (isRightDevice && [self checkUserDistanceWith:model]) {
                    _tryConnectBeacon = model;
                    *stop = YES;
                }
            }];
        }
    }
    
    if (!_tryConnectBeacon) {
        return;
    }
   
    //开始连接
    if (_isTryConnecting) {
        return;
    }else{
        _isTryConnecting = YES;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self->_isTryConnecting = NO;
        });
    }
    msg = [NSString stringWithFormat:@"开始连接ibeacon设备 %@ major = %@,minor = %@",_tryConnectBeacon.deviceNo,_tryConnectBeacon.major,_tryConnectBeacon.minor];
    [UserManager updateLogViewWithMessage:msg needUnicode:NO];
    [[SLBluetoothManager sharedManager] startSearchDeviceAndConnect:_tryConnectBeacon.deviceNo isBridge:NO finish:^(BOOL isSuccess, CBPeripheral *peripheral, id data, NSString *errorMsg) {
        if (isSuccess) {
            [ZCTool hideLoadingOnKeyWindow];
            kCurDevice = _tryConnectBeacon;
            msg = [NSString stringWithFormat:@"连接上了设备 %@ major = %@,minor = %@",_tryConnectBeacon.deviceNo,_tryConnectBeacon.major,_tryConnectBeacon.minor];
            NSLog(@"%@",msg);
            [UserManager updateLogViewWithMessage:msg needUnicode:NO];
            [ZCTool showLocalNotfyAlertWith:kLocalString(@"Tips") body:msg];
            
        }
    }];
}

//判断当前设备和设置的双模开锁范围是不是匹配
-(BOOL)checkUserDistanceWith:(SLLockModel *)model{
    if (!_userLocation) {
        return NO;
    }
    if (model.dbLatitude.length == 0 || model.dbLongitude.length == 0) {
        return NO;
    }
    //在范围内
    CLLocation *deviceLocation = [[CLLocation alloc] initWithLatitude:[model.dbLatitude doubleValue] longitude:[model.dbLongitude doubleValue]];
    NSInteger distance = [self calculateDistanceBetween:_userLocation and:deviceLocation];
    if (distance <= model.regionDistance) {
        return YES;
    }
    return NO;
}

- (CLLocationDistance)calculateDistanceBetween:(CLLocation *)location1 and:(CLLocation *)location2 {
    if (!location1 || !location2) {
        NSLog(@"One or both locations are nil.");
        return -1; // 返回 -1 表示计算失败
    }
    // 计算两地之间的距离（单位：米）
    CLLocationDistance distance = [location1 distanceFromLocation:location2];
    return distance;
}

// CLLocationManagerDelegate 方法
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    CLLocation *location = [locations lastObject];
    _userLocation = location;
    [_locationManager stopUpdatingLocation];
}

-(CLRegion *)region{
    if (!_region) {
        NSUUID *proximityUUID = [[NSUUID alloc] initWithUUIDString:kIBeaconUUID];
        _region = [[CLBeaconRegion alloc] initWithProximityUUID:proximityUUID identifier:@"ibecon"];
        _region.notifyOnEntry = YES;
        _region.notifyOnExit = YES;
        _region.notifyEntryStateOnDisplay = NO;
    }
    return _region;
}

-(CLLocationManager *)locationManager{
    if (!_locationManager) {
        _locationManager = [[CLLocationManager alloc] init];
        _locationManager.delegate = self;
        _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//        _locationManager.allowsBackgroundLocationUpdates = YES;
        // Set a movement threshold for new events.
        _locationManager.distanceFilter = kCLDistanceFilterNone;
    }
    return _locationManager;
}

@end
